// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license


#include "stdafx.h"
#include "WorldBuilder.h"
#include "Geometry.h"
#include "Sphere.h"
#include "Triangle.h"
#include "Quad.h"
#include "Ray.h"
#include "Node.h"
#include "AABB.h"

// TODO turn of lighting when drawing in wireframe mode

// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

void Cube::draw(View3d* view) const
{
    Quad faces[6];
    getAllAabbFaces(faces);

    //glPushAttrib(GL_POLYGON_BIT);
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    for(int faceIdx = 0; faceIdx < 6; ++faceIdx)
    {
        Quad & q = faces[faceIdx];
        //glColor3dv(faceIdx == m_hoverFace ? 
        //		hilightColor.to_array() : baseColor.to_array());
        drawQuad(q);
    }
}

ref<Geometry> Cube::clone() const
{
    return ref<Geometry>(new Cube(*this));
}

AABB Cube::getAABB() const
{
    return AABB(gx::Vec3(1., 1., 1.), gx::zero);
}


// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =


ref<Geometry> SphereShape::clone() const
{
    return ref<Geometry>(new SphereShape(*this));
}

void SphereShape::draw(View3d * view) const
{
    glPushMatrix();
    glRotated(90., 1., 0., 0.);
    //if(m_wireframe)
    //{
    //	glutWireSphere(.5, 10, 10);
    //}
    //else
    //{
    // TODO fix wireframe
    glutSolidSphere(.5, 20, 20);
    //}
    glPopMatrix();
}

AABB SphereShape::getAABB() const
{
    return AABB(gx::Vec3(1., 1., 1.), gx::zero);
}


// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =


ref<Geometry> CylinderShape::clone() const
{
    return ref<Geometry>(new CylinderShape(*this));
}



void drawCylinder(double r, double height, bool drawCaps=true)
{
    int res_ = 10; // WAS: 15
    double delta = TWO_PI / (res_-1);
    std::vector<gx::Vec3> vertices[2] = { std::vector<gx::Vec3>(res_), std::vector<gx::Vec3>(res_)};
    std::vector<gx::Vec3> normals(res_);
    for(int i = 0; i < res_; ++i)
    {
        double theta = i * delta;
        double s = sin(theta);
        double c = cos(theta);
        vertices[0][i] = gx::Vec3(r * c, r * s, 0);
        vertices[1][i] = gx::Vec3(r * c, r * s, height);
        normals[i] = gx::Vec3(c, s, 0);
    }

    // TODO Switch to "cull back faces" mode

    // Draw the side
    glBegin(GL_QUAD_STRIP);
        for(int i = 0; i < res_; ++i) 
        {
            glNormal3dv(normals[i].to_array());
            glVertex3dv(vertices[1][i].to_array());
            glVertex3dv(vertices[0][i].to_array());
        }
    glEnd();

    if(drawCaps)
    {
        // Draw the bottom
        glBegin(GL_TRIANGLE_FAN);
            glNormal3d(0., 0., -1.);
            for(int i = 0; i < res_; ++i) 
            {
                glVertex3dv(vertices[0][i].to_array());
            }
        glEnd();

        // Draw the top
        glBegin(GL_TRIANGLE_FAN);
            glNormal3d(0., 0., 1.);
            for(int i = 0; i < res_; ++i) 
            {
                glVertex3dv(vertices[1][i].to_array());
            }
        glEnd();
    }
}

void CylinderShape::draw(View3d * view) const
{
    glPushMatrix();

    // Account for the fact that our "drawSolidCylinder" function
    // places the origin at one of the bases, when we want
    // the origin to be at the cylinder's center. We divide the 
    // y component by the Y scale to compensate for the fact that
    // the base class has already scaled the modelview matrix
    glTranslated(0., -.5, 0.);

    // Account for the fact that our "drawSolidCylinder" function
    // draws the cylinder aligned with the Z axis, when we want
    // it aligned with the Y axis
    glRotated(90., -1., 0., 0.);

    // TODO Don't draw caps in wireframe mode
    drawCylinder(.5, 1., true);		

    glPopMatrix();
}



AABB CylinderShape::getAABB() const
{
    return AABB(gx::Vec3(1., 1., 1.), gx::zero);
}


